#!/usr/bin/env python3

from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import *
from test_framework.script import *
from test_framework.mininode import *
from test_framework.address import *
from test_framework.qtum import *
import pprint
import subprocess

pp = pprint.PrettyPrinter()

class QtumEVMConstantinoplePrecompiledContractsTest(BitcoinTestFramework):
    def set_test_params(self):
        self.setup_clean_chain = True
        self.num_nodes = 1
        self.extra_args = [['-txindex=1', '-logevents=1', '-constantinopleheight=1000000']]

    def skip_test_if_missing_module(self):
        self.skip_if_no_wallet()

    def send_and_call_method(self, abi, point=False):
        print(abi)
        self.last_txid = self.node.sendtocontract(self.contract_address, abi, 0, 10000000)['txid']
        self.node.generate(1)
        if point:
            ret = self.node.callcontract(self.contract_address, "767f2a89")['executionResult']['output']
            ret += self.node.callcontract(self.contract_address, "a1461eef")['executionResult']['output']
        else:
            ret = self.node.callcontract(self.contract_address, "1b08d96f")['executionResult']['output']
        return ret

    def reset(self):
        self.node.sendtocontract(self.contract_address, 'd826f88f')
        self.node.generate(1)

    def ecrecover_test(self):
        cases = [
            # use private key b"\x00"*32, this should fail, so output is b"\x00"*32
            '7c1886d96dc50f07a48fa7d72006809ac9f45d6b1c34b7a072ace679674c64a230aac08d000000000000000000000000000000000000000000000000000000000000001c9c88b967e65708ae5b744502ec117fae31b7f787753e63d8cea7047e789bd55d1d5557b6eca94f4f7473c862cfb5488980d7e1e3eb764f5f11b0fe2281931d2e',
            '0000000000000000000000000000000000000000000000000000000000000000',

            # use message b"\x00"*1024
            '7c1886d9b5d4d1df10388bbc208778ff02310db98fdaa68efed0b2068a9bef78bd3bfd74000000000000000000000000000000000000000000000000000000000000001c02637881f72c93e6e29b4086aeb5600c862189bcc7ac7f0a2659975f1391d9e921b305c078bea4a33f154b2ace7f712b317132d106d909376770aa06fb756a25',
            '000000000000000000000000d32d23c9f11181971cc2163fa5f4f3b4685250ae',

            # radmon generated data set
            '7c1886d9f490f787ba2101ce9f72a58a7d82acdf32993fc52e6a13eb1395d3404c9e9b21000000000000000000000000000000000000000000000000000000000000001b9bdb59ce2220374bebf8293f9d585695f672669232217d8e83b32b23ca2806562cee90009f39b3f7469a9b2fb589acaf543c8d55411a7be9afb72a97c4b73ce9',
            '0000000000000000000000004f54f1246244bae9a23b8dea4a6a5e0722bcc7af',

            '7c1886d97250aed04dd0f9a0e35a43518cd3417c138c5feb2a7076e24b459e11208de51d000000000000000000000000000000000000000000000000000000000000001c5068b13e6508cd1f59b82707a4b062106e79176f9880052f5dadcf48282c0b043950e2a36e8e5dada244d0d5161435dfdf1ef16079feb2ec13fa84d2bab2f3c0',
            '000000000000000000000000b30802ef79545a4099b9ed66fd7a3bea5e5e8069',

            '7c1886d95f9b0413e1854cbe5ac199573d721d612a60e0dc8d33abe542201a7f26005912000000000000000000000000000000000000000000000000000000000000001b9673ecfb2cabfeac36518de803d0e31bc1fe5108d902928f24c847ca4920f24e77dacf3e9fbed0fc44dee07a0f17811e4e1211dbdcf2c71b3610dfcee6a78eac',
            '000000000000000000000000a87050c8b8ada33f14ef25f8f1aaa717adfbc361',

            '7c1886d9cf9074f027fbd1361e8cf0a54648eeeb430e995761628a275de2596ec621d811000000000000000000000000000000000000000000000000000000000000001cd50b8acfe5be99f1d886d6d328659870550b0fcd6c714087ec78d4858c35454d2f5cc6ef18d1f40f734a848c686a155dac5bab8a6a605bc23f9f9d65c5c2a680',
            '00000000000000000000000016ad646a906a0166e464b777c5c8fe241ba1e2b1',

            '7c1886d9b2b9b8d17edb52518ba589939a7dae09f21cc7864b8dbf8f10332697907f0ee0000000000000000000000000000000000000000000000000000000000000001c0f5dbd15a5e1eaf60130b5f5c8259d73f8b6c74b50592f1fec2d4a7a84b2f76653d1d57989cc5c156acb63ba42d29dc31927d32bac53174e6ef969edb29f17f8',
            '00000000000000000000000062985497e536c37b380321b015ec0abcd79ec7bc',

            '7c1886d96a73c7c3701605d2958a83c8866235b1d1fab380ca789d41cc8e47fe61615fcd000000000000000000000000000000000000000000000000000000000000001c9023000c14921c8ab1194e354fed920894186dbc6c8f5227765b07c16f8a1e5042a05641731af4c3422baebd6918ff6d8052317052f3832a9b62ecade0095699',
            '000000000000000000000000016fcf577ef4aaa4a2d45625831c0e704e4e3d74',

            '7c1886d94b344eceab3de0054f9ab25dc3b717ba1549bad862d19cbe158cda24819edfac000000000000000000000000000000000000000000000000000000000000001bb0dab103bc228acd28dade4b994e82d5f5dcd828b8187096b88411fc183914262b4e1b19e220c1c644eaf337c172e6cd6b9441d5085d1c7b28c0b8983bbe8524',
            '000000000000000000000000fd8335a736b887af45c0371ea8fb0a573e26ae3d',

            '7c1886d93e2b38946494ead1ad55c5de8f3ed7c27ca6ac49e6695ca9ffc246228a84a988000000000000000000000000000000000000000000000000000000000000001c0f8dd19c738ab674db0c8ed49f801b4537be06cf065ce0e1efbb9848cab638301df4e131efe10da58f11da306935635301d323ffc9317bff5f2a17197fc42918',
            '000000000000000000000000a3b573d5b3777daf6ff43a6c6ba230a6752592d4',

            '7c1886d90d5ca24233daf378d9191781a7175608663cb4ea295c29e84b044c82d353792e000000000000000000000000000000000000000000000000000000000000001bef6ab0777b83e95f2ffda28e8830653899c423d26844df1cf5d9eee0e1b7341057377689a70d467f939a46353e0957e64f4e71477b2befe484f903404ca26599',
            '000000000000000000000000a4379b7bb3b16e533c98b039bc49812bc9394e43',

            '7c1886d909611342bb9a099f754c3594a0fc4b1e9ef54f0fddabf247ae2bace040ac7bb2000000000000000000000000000000000000000000000000000000000000001caf9e9fb2de96c241427b385d0a46cbcd289ed1afa8f4f73cc7cca01d9cb34b5a6cc216073a7401cc78afdf4bedbc4884e797d2f28e3a09cc67508fd00216c1b3',
            '0000000000000000000000005a36aca3ae19fee3eca8bdaca7be0ecc0573b0a2',

            '7c1886d91314d07e0d781d481477dd9df89007f66bf7cd480664eeca8033cd9edcd40396000000000000000000000000000000000000000000000000000000000000001b91f7e128172e8c8ac5902a76aebfa5a6c848ccf559ec775f38de31ed26c9e2e47da785918773682e72317330f4b434e914c14e5c58a21b430b8f160a976c4a07',
            '000000000000000000000000107ccd80e5a15814a8c71b54483880a2df9f1edc',

            '7c1886d91597dbc56b18741d74163ea2c3eacaf3acfb5c88a77fa9467de3213fb2494017000000000000000000000000000000000000000000000000000000000000001cf9f13829c7d96e35c31a92c80a584483f21a7cad02728d59a594bb172e1d8f1260fcaf14482b80ee82dff4cb62afcf22e646227a5c764544e9e10eeb2e8dc0ba',
            '0000000000000000000000007356c0bd3e18962e6e90fd3db9797cb18372aef8',

            '7c1886d950d848acf661fcfb72292916ee401e8dbc773b3f1a421a9126c003ad052ecfa2000000000000000000000000000000000000000000000000000000000000001c56e0ac06963bb231d9689b44bd7b1448c50c29896ae7e176f2d085aefdaa01b14f387d838a53c83ad582a396f2c52a6de2ac1503442da484b56ff1633f88fb93',
            '000000000000000000000000d496aba349085837deaea77db539295ef52ce890',

            '7c1886d9f0d6c13034ae0a5790a4be3e12c75fb45076b1a5f1996382ebd3ba2b5cc36e97000000000000000000000000000000000000000000000000000000000000001cb88505d6994e3b6bbca213b3acbb62e77fab853d276968e0c78172e0df46e44e24c309b1cc6a78e58a62a33d3688a2480e5715c8219f9f4252cbd2e3973982ec',
            '000000000000000000000000bd634693ff3e83a500a3d62828a71228387f9642',
            '7c1886d97a8f78d4af1d905ab2fc218e92ee9b4e547e6023d5697659adeb95f4089ce4e2000000000000000000000000000000000000000000000000000000000000001b00cbc1f3e82ecec91ae8719a7ddc959573f9251412537918729057d49d17c9e05f16692b787bd6708b182c8ed255f41d9b7b3a1bce350f42bafdfecf9af85cbf',
            '0000000000000000000000001399e4d330722b1ea712af241dc9af9a758dca14',

            '7c1886d957880dd92ef5bdaf0044c5df8992fb15170bc161c48ab4f785086259e202bcac000000000000000000000000000000000000000000000000000000000000001c926f540902416e161e09e529f9813fb731637d82f91a3874d8e4d2268ca25eb13773ab20c414ed5790db4925e58ce3c5ca668d67d8fb2d45e0aedeb8ae86bb77',
            '00000000000000000000000074e4557e80ef1500b5fdd3cb7d71ae41ea427ba8',

            '7c1886d91b777bf54f05334d9462efe78ffd70b0d971e27df7d8ce9893e8e1dc911eaf8e000000000000000000000000000000000000000000000000000000000000001c6775824b761923a6d25f8a481457f72ab00a339ba851cb24afff16d1131f58785d91c468053f4488f06cdfcd18adc730b59473b00f87a6cefb91a13917046287',
            '0000000000000000000000000405862b5559d869173bac3aa8a73d852d5732a4',

            '7c1886d99f2024d49deed8eae41e61005839cd658a85a971bab4a6ec78cfb20cfc99f254000000000000000000000000000000000000000000000000000000000000001cf1de1b77e4408c97b0ecc1e4cd388ed0c7304b77be7d8c87474dcb9356db2bd364dddf49fb0681d5d64b95cee2448285b60e123ffabc2a2303a7ee4e2e8d0348',
            '000000000000000000000000ba4a4506cf27c9c9c29f1e6e199372e2f048d428',

            '7c1886d9da02f38f81d3405d4c4ea7756b44eedfc64ab15f93ad0cdd03aa366686d95804000000000000000000000000000000000000000000000000000000000000001c01bad6bdf71094ca8f9301fd70b1514a478d6f4718a73d190eaa5ded6a498ee936f2e74930e9091762ef6422c2e756bc5546aefedfc6c4b8254deefc4cb063da',
            '000000000000000000000000da08935e20234eb636f478ef1ae231086d9bb98c',

            '7c1886d965a8810d009890a9af4f0609efecfdd37e049364013e7fb7fce80c1e277d87c5000000000000000000000000000000000000000000000000000000000000001c406f6ac3c231ee629e550b4e7ae7104f4caa26701beb38a81f30420d3e7808e340ac46514352538369c289ac625826ba13698396393c96a7a0efda8611115fe1',
            '0000000000000000000000008618d455ebfad54a19936c1fb3dc13d7f4f92f50',

            '7c1886d99bcacd967e8c89ce69ee185b049b49aeb6071f1fd0cfb0e816f3e113252fafa3000000000000000000000000000000000000000000000000000000000000001c434ad762a0e2c7d37e29814a9ea632d7752bfa9b84b1682fb514069db117d9e254bdfae37c9454c626b5b47b5cbd70fc3ad1178a7fdfb0060ca9477e21942fb6',
            '0000000000000000000000008dfc191dfe61a45dab291cd472f96ea770354a1b',

            '7c1886d9681f968173991d634b52ac3af40669936d5bc25e1eeca29518721c9bb2976c53000000000000000000000000000000000000000000000000000000000000001cf6f36af5379d9c64e1275d2737ac135120bea6ee3017fb091e8b94e0e54148ec64affca5498a77e507392476b9c784cf00478297c1bbbf4c181628f7ce58810b',
            '00000000000000000000000006c56f67fda5a5fe468b77c20f225d17a30cde0d',

            '7c1886d95f36dbebfa6ff4d35a633fd0dd2beac7881627cfc0d5210300e256d688fa5710000000000000000000000000000000000000000000000000000000000000001c9b1fe821195abef93d6d25b2a570fb6ddad4c009a02e52ef7ab081e6a06563710abaa71d3df137868cb5abf4c7340b8eb3cee9cf16c5bcd6e7a7a4d12268678a',
            '00000000000000000000000031b70bb97c9bf3b9531d2011325c581872a48110',

            '7c1886d92794cdeb392db9c393134e5d5b0c203e9d2d2216eab39cc328691e930cd0b247000000000000000000000000000000000000000000000000000000000000001ca5ac49a2084a8ad1784f2d10d6d3ca79255cf9fd45768f472980e1157899aaa21473ab24eea963f02d25d38f4705f7f2e73fc0d214dbbe703248380e6186b4f8',
            '000000000000000000000000c7adb89ce8a5e4cf911d4122485c3451cce96a2f',

            '7c1886d91dab0491305d2038f947f931ebc4f501b48db6355c838af90bf625d68ec463e5000000000000000000000000000000000000000000000000000000000000001c9d708f6c937f44f1b99738c73c214bfd3333e6cfdc640d1b99d979140d009ff93a7ff98a1804dad2aa4b8e0f14c3be2341b2ab8b89c42520004358038e9c12cf',
            '00000000000000000000000090d3d255397640ec2827bd205f6c4bed685a7d1c',

            '7c1886d9b85104eaa5293d6c6471951811c368d5c7473abb29c63340153ef0e7159b9f7c000000000000000000000000000000000000000000000000000000000000001bd7c847c077bb1ba771891cf744ad394330e54be5553b3d23f30cdcac8ea3ba7a625f11ca98ef2722a01c87e0e4c96247551a3387c5429afe97604d2c841548eb',
            '0000000000000000000000009c92800d00934defd1044e57f4cf821f0134da0f',

            '7c1886d9ab81f6f3fde02ff561ad5296e03527e3a76f90fea5b57f2e60edc6996126e48e000000000000000000000000000000000000000000000000000000000000001bc8eca2230625b8e16e1497ab3f75cffcb87f38c21443412fbacdc2a33d4b3efd51f6883f5344bc37a78e3dc165044073c157753cb15688ffee408de512d1cfdb',
            '0000000000000000000000004bad751caa111f985daf62a78ceeb990fb8a1d1a',

            '7c1886d9ec2fd40c1e531fc681b8db1c75596d04a3347fe6fcd593dfffb537a95f9995f2000000000000000000000000000000000000000000000000000000000000001c120d0240ee0602f1cc467c0bdf0a62ef5720dcbbf8f74ea5176e4524aeb12ae54c378a59643311389c6c35cadfd53d92fb87d80f253f5e2f2b99746da965038c',
            '0000000000000000000000006c5713ce99e7b8765295fd1d0aa222e2dd63ad0e',
            '7c1886d9987f177b5644da1c9da525e97bf2fa526ecbef2992cc8636c026d21f484f1867000000000000000000000000000000000000000000000000000000000000001b74249a09ba188562c885b3bf460e79456b15bb6b124465bd4330692fbe957cb755effeac33df08e9ab43d92dd695403662b59349cf914e9eeaa3002a829c3b58',
            '000000000000000000000000957c72d900768f6c0772669f2261050d73fd70f0',

            '7c1886d9fe36e4e12dae2fdf8b88a65e39260d7b337ac167a79b5204cc5d5509556f5864000000000000000000000000000000000000000000000000000000000000001c7720582b196e09ed4daa63959bb7a1c682012b4ad30fe43a1c14e41a7604f0aa2aa623d17d3d0f45a1668b4b9a745cb7dcf5d307ac60040674535cce49ba9afe',
            '000000000000000000000000c1e0158752f56d2d111c1a4db485b0e52d31f88d',

            '7c1886d9eb2a1099bbb10196437a75023cdc5bfaf74900b57ae3168a96f5798269c2923a000000000000000000000000000000000000000000000000000000000000001cea2679060b6fa48088b901a3249e1ef637b9cec513e50a48ed2c61769c30d7b951a17b245249bb5cb6aac8e84fa40dc6246ac5ba4bc763bd6f14bac1ca7f302c',
            '00000000000000000000000053d3bf34df249e24da25a78ff14decd92ed6b65f',

            '7c1886d9636cb175f8752865d39b0e52802a9b4c7e1ac1550d467c2c284b05330ece6473000000000000000000000000000000000000000000000000000000000000001bd201b9ebf04132442b6cc325b5337ce7274080142a514dbd2933691669c7bbbb5f18f4f1f827be77367259ce49a2b67711a8f1b1bb06d4483987888ed0aa4053',
            '0000000000000000000000003fe0a700914f713bfbd60a28518d40eb1865de6b',

            '7c1886d9a2a81992aa8eb0376fc768d45029d0f8ee9638729766f050609fa59d6b8a74e5000000000000000000000000000000000000000000000000000000000000001b8986b652053f6a725cc6698e81bc3a03efec1d8c00a34f1bc44968eb38fbfdd66b79929d6def3809f228095f6c7618cbe83d9ea5acc52d4d7b88583f770db0ac',
            '0000000000000000000000000365e882a0d4da20eacbb54f15dfc4c95228cec0',

            '7c1886d95d1372a27abd2abaaeb8b596f5dbb9cfd69641072e6cc5ac94e7008000c50749000000000000000000000000000000000000000000000000000000000000001b6fab1e3db54ae0da6ce10b356d2a1d6d8d0d8a913414d57186b4d2f209daa21f353340b12f4a049d3c85930329165309438e70d6cdf121dcdb5e66a908c77a9c',
            '0000000000000000000000006b5036d09f6de2e7cebe7f4d05fc1d67deb5c5cc',

            '7c1886d935d58bf4e7fc6176cd4865f28a23b5aea54e95017984e3d244842ffaab7ea239000000000000000000000000000000000000000000000000000000000000001c970d5ae3c784cdf14f5e2eef19e2854ec3dd2ac7b084cd4cdce85ca4daf4908204ef2ff7a0894312157ebc2c3060441a12385ce9d98e2e9970e15b88b6a2fa3a',
            '00000000000000000000000011c10d5c295cb54f5d2fad1ec759fd1fc7f79ba9',

            '7c1886d9f8803fa369dce2bad475648f4227c0ea3465b59b5039daa0abdd0af06ccbb7ab000000000000000000000000000000000000000000000000000000000000001c31b46f427db3d8a9b2944f4befe4150bf38114af553c22c0100dc87cfb59ad2347597cc25953a700e3ed170a43b0c05acc0688c345188bccdfc277b651ac1759',
            '000000000000000000000000f940a3655f490ae157325dcc226d5d61befd1136',

            '7c1886d9b738020e5a0fa76b3df7e1404cd1e6831292a3d91c2f9fc1c787e6b7e733835e000000000000000000000000000000000000000000000000000000000000001bc6517057279c059ef2ea68ecced58526ddbd88b0e92b539b66423ea8ca8262624ccf5b74c8e770d102d2191edc9282b5ad6c9e77f98a3b62ace7583d4a5a2a47',
            '00000000000000000000000043b0c2046e8b03647dbc22977e204c5a6bec8f5e',

            '7c1886d96a9fa2fc110114404d7fe701f7c602c731f648652e7c76d993fee5db5012060c000000000000000000000000000000000000000000000000000000000000001c5ed8b1932be9f6a132e354cfc452f1555ffb74add87776bc4e3eaab34ed28c105ef99e9b456e4e4776681b8e36aa4763ea090f78ac9860c24211b28bb94a5082',
            '00000000000000000000000006352e6be5e5f88cf9f5da078725e7212fd3acd9',

            '7c1886d9c921fae289d6e059b5cef185112e2017a3e5e70ebaa91e126ed866fd5316e79e000000000000000000000000000000000000000000000000000000000000001bca2770bb42a37452200b15f362b05f3302896fc14d451f4f090a6bfe9afac45f1e7ed76d38be23ad29b46172faee9a4d894c7ac816ed4a92ab598bee92bb798e',
            '000000000000000000000000c17a9bc69789b1281f87a6343664a3f7742c98b2',

            '7c1886d99538f392af49bbfbd1d15dd7410500c74b9dc75e5b064f6f75e5f1768e9b4735000000000000000000000000000000000000000000000000000000000000001bb87f93d1299ac512d5a729d196e2adc81c7bb62d8ce7a86d28847a9ad3b32d4130b6d613aaae70a5f3594a0c5e1ff9f54332b922e604f025fe68d13ca2da5b81',
            '000000000000000000000000fb2c379b5bbb8c3b82a24cbbb291535e15d1e573',

            '7c1886d9458ea175ee548c59a0c56f1625f57f0de88964f17ec72f9ce4ed528dafbf87fb000000000000000000000000000000000000000000000000000000000000001cc2e436cc6a6274f41f1d76c2fa72423ec0b12fd6d924a49f5e1df8327d0076184ecc3b46832a4f45e403c530fb2897c3f29b59a2027e8116d8ec8d70e90ca44e',
            '000000000000000000000000afcc275b880ca519f4a4b08cfc4dad215310c179'
        ]

        i = 0
        while i < len(cases):
            print(i)
            in_val = cases[i]
            out_val = cases[i+1]
            ret = self.send_and_call_method(in_val)
            assert_equal(ret, out_val)
            i += 2

    def sha256_test(self, should_fail=False):
        def test(message):
            if message is None:
                message = hex(random.randint(0, 2**256))[2:].zfill(64)
            else:
                message = message.encode('utf-8').hex().zfill(64)
            in_val = hex_str_to_bytes(message)
            abi = "12bdedd7"
            abi += "20".zfill(64)
            abi += hex(len(in_val))[2:].zfill(64)
            abi += bytes_to_hex_str(in_val) + ("00" * (32 - len(in_val)))
            ret = self.send_and_call_method(abi)
            assert_equal(ret, hashlib.new('sha256', in_val).hexdigest())

        test("")
        test("a")
        test("abc")
        test("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")
        test("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu")
        test("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno"*1024)

        # random tests
        for _ in range(100):
            test(None)

    def ripemd160_test(self, should_fail=False):
        def test(message):
            if message is None:
                message = hex(random.randint(0, 2**256))[2:].zfill(64)
            else:
                message = message.encode('utf-8').hex().zfill(64)
            in_val = hex_str_to_bytes(message)
            abi = "e3c87216"
            abi += "20".zfill(64)
            abi += hex(len(in_val))[2:].zfill(64)
            abi += bytes_to_hex_str(in_val) + ("00" * (32 - len(in_val)))
            ret = self.send_and_call_method(abi)
            assert_equal(ret[0:40], hashlib.new('ripemd160', in_val).hexdigest())

        test("")
        test("a")
        test("abc")
        test("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")
        test("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu")
        test("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno"*1024)

        for _ in range(100):
            test(None)

    def identity_test(self, should_fail=False):
        def test(message):
            if message is None:
                message = hex(random.randint(0, 2**256))[2:].zfill(64)
            else:
                message = message.encode('utf-8').hex().zfill(64)[:64]
            in_out_val = message
            abi = "3d9c8fdb"
            abi += "20".zfill(64)
            abi += hex(len(in_out_val) // 2)[2:].zfill(64)
            abi += in_out_val
            ret = self.send_and_call_method(abi)
            assert_equal(ret, in_out_val)

        test("")
        test("a")
        test("abc")
        test("a"*32)
        test("abcd"*8)

        for i in range(100):        
            test(None)

    def modexp_test(self, should_fail=False):
        for _ in range(100):
            self.reset()
            base = random.randint(0, 2**256)
            e = random.randint(0, 2**256)
            m = random.randint(0, 2**256)
            abi = "fdcd12cb"
            abi += hex(base)[2:].zfill(64)
            abi += hex(e)[2:].zfill(64)
            abi += hex(m)[2:].zfill(64)
            ret = self.send_and_call_method(abi)
            if should_fail:
                assert_equal(ret, "0000000000000000000000000000000000000000000000000000000000000020")
            else:
                assert_equal(int(ret, 16), pow(base, e, m))

    def bn256add_test(self, should_fail=False):
        cases = [
            "18b18acfb4c2c30276db5411368e7185b311dd124691610c5d3b74034e093dc9063c909c4720840cb5134cb9f59fa749755796819658d32efc0d288198f3726607c2b7f58a84bd6145f00c9c2bc0bb1a187f20ff2c92963a88019e7c6a014eed06614e20c147e940f2d70da3f74c9a17df361706a4485c742bd6788478fa17d7",
            "2243525c5efd4b9c3d3c45ac0ca3fe4dd85e830a4ce6b65fa1eeaee202839703301d1d33be6da8e509df21cc35964723180eed7532537db9ae5e7d48f195c915",

            "2243525c5efd4b9c3d3c45ac0ca3fe4dd85e830a4ce6b65fa1eeaee202839703301d1d33be6da8e509df21cc35964723180eed7532537db9ae5e7d48f195c91518b18acfb4c2c30276db5411368e7185b311dd124691610c5d3b74034e093dc9063c909c4720840cb5134cb9f59fa749755796819658d32efc0d288198f37266",
            "2bd3e6d0f3b142924f5ca7b49ce5b9d54c4703d7ae5648e61d02268b1a0a9fb721611ce0a6af85915e2f1d70300909ce2e49dfad4a4619c8390cae66cefdb204",

            "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
            "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",

            "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
            "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",

            "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
            "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",

            "",
            "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",

            "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
            "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",

            "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002",
            "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002",

            "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
            "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002",

            "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002",
            "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002",

            "0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
            "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002",

            "000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
            "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002",

            "0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002",
            "030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd315ed738c0e0a7c92e7845f96b2ae9c0a68a6a449e3538fc7ff3ebf7a5a18a2c4",

            "000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
            "030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd315ed738c0e0a7c92e7845f96b2ae9c0a68a6a449e3538fc7ff3ebf7a5a18a2c4",

            "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa901e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7c039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b869073a5ffcc6fc7a28c30723d6e58ce577356982d65b833a5a5c15bf9024b43d98",
            "15bf2bb17880144b5d1cd2b1f46eff9d617bffd1ca57c37fb5a49bd84e53cf66049c797f9ce0d17083deb32b5e36f2ea2a212ee036598dd7624c168993d1355f",

            "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa901e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7c17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa92e83f8d734803fc370eba25ed1f6b8768bd6d83887b87165fc2434fe11a830cb00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
            "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
        ]

        i = 0
        while i < len(cases):
            print(i)
            in_val = cases[i]
            print(in_val)
            out_val = cases[i+1]
            abi = "5327e297"
            abi += in_val
            ret = self.send_and_call_method(abi, point=True)
            if should_fail:
                assert_equal(ret, in_val[0:128] if len(in_val) >= 256 else "0"*128)
            else:
                assert_equal(ret, out_val)
            i += 2

    def bn256scalarmul_test(self, should_fail=False):
        cases = [
            "2bd3e6d0f3b142924f5ca7b49ce5b9d54c4703d7ae5648e61d02268b1a0a9fb721611ce0a6af85915e2f1d70300909ce2e49dfad4a4619c8390cae66cefdb20400000000000000000000000000000000000000000000000011138ce750fa15c2",
            "070a8d6a982153cae4be29d434e8faef8a47b274a053f5a4ee2a6c9c13c31e5c031b8ce914eba3a9ffb989f9cdd5b0f01943074bf4f0f315690ec3cec6981afc",

            "070a8d6a982153cae4be29d434e8faef8a47b274a053f5a4ee2a6c9c13c31e5c031b8ce914eba3a9ffb989f9cdd5b0f01943074bf4f0f315690ec3cec6981afc30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd46",
            "025a6f4181d2b4ea8b724290ffb40156eb0adb514c688556eb79cdea0752c2bb2eff3f31dea215f1eb86023a133a996eb6300b44da664d64251d05381bb8a02e",

            "025a6f4181d2b4ea8b724290ffb40156eb0adb514c688556eb79cdea0752c2bb2eff3f31dea215f1eb86023a133a996eb6300b44da664d64251d05381bb8a02e183227397098d014dc2822db40c0ac2ecbc0b548b438e5469e10460b6c3e7ea3",
            "14789d0d4a730b354403b5fac948113739e276c23e0258d8596ee72f9cd9d3230af18a63153e0ec25ff9f2951dd3fa90ed0197bfef6e2a1a62b5095b9d2b4a27",

            "1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f6ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
            "2cde5879ba6f13c0b5aa4ef627f159a3347df9722efce88a9afbb20b763b4c411aa7e43076f6aee272755a7f9b84832e71559ba0d2e0b17d5f9f01755e5b0d11",

            "1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f630644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000",
            "1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe3163511ddc1c3f25d396745388200081287b3fd1472d8339d5fecb2eae0830451",

            "1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f60000000000000000000000000000000100000000000000000000000000000000",
            "1051acb0700ec6d42a88215852d582efbaef31529b6fcbc3277b5c1b300f5cf0135b2394bb45ab04b8bd7611bd2dfe1de6a4e6e2ccea1ea1955f577cd66af85b",

            "1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f60000000000000000000000000000000000000000000000000000000000000009",
            "1dbad7d39dbc56379f78fac1bca147dc8e66de1b9d183c7b167351bfe0aeab742cd757d51289cd8dbd0acf9e673ad67d0f0a89f912af47ed1be53664f5692575",

            "1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f60000000000000000000000000000000000000000000000000000000000000001",
            "1a87b0584ce92f4593d161480614f2989035225609f08058ccfa3d0f940febe31a2f3c951f6dadcc7ee9007dff81504b0fcd6d7cf59996efdc33d92bf7f9f8f6",

            "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa901e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7cffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
            "29e587aadd7c06722aabba753017c093f70ba7eb1f1c0104ec0564e7e3e21f6022b1143f6a41008e7755c71c3d00b6b915d386de21783ef590486d8afa8453b1",

            "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa901e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7c30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000",
            "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa92e83f8d734803fc370eba25ed1f6b8768bd6d83887b87165fc2434fe11a830cb",

            "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa901e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7c0000000000000000000000000000000100000000000000000000000000000000",
            "221a3577763877920d0d14a91cd59b9479f83b87a653bb41f82a3f6f120cea7c2752c7f64cdd7f0e494bff7b60419f242210f2026ed2ec70f89f78a4c56a1f15",

            "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa901e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7c0000000000000000000000000000000000000000000000000000000000000009",
            "228e687a379ba154554040f8821f4e41ee2be287c201aa9c3bc02c9dd12f1e691e0fd6ee672d04cfd924ed8fdc7ba5f2d06c53c1edc30f65f2af5a5b97f0a76a",

            "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa901e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7c0000000000000000000000000000000000000000000000000000000000000001",
            "17c139df0efee0f766bc0204762b774362e4ded88953a39ce849a8a7fa163fa901e0559bacb160664764a357af8a9fe70baa9258e0b959273ffc5718c6d4cc7c",

            "039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b869073a5ffcc6fc7a28c30723d6e58ce577356982d65b833a5a5c15bf9024b43d98ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
            "00a1a234d08efaa2616607e31eca1980128b00b415c845ff25bba3afcb81dc00242077290ed33906aeb8e42fd98c41bcb9057ba03421af3f2d08cfc441186024",

            "039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b869073a5ffcc6fc7a28c30723d6e58ce577356982d65b833a5a5c15bf9024b43d9830644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000",
            "039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b8692929ee761a352600f54921df9bf472e66217e7bb0cee9032e00acc86b3c8bfaf",

            "039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b869073a5ffcc6fc7a28c30723d6e58ce577356982d65b833a5a5c15bf9024b43d980000000000000000000000000000000100000000000000000000000000000000",
            "1071b63011e8c222c5a771dfa03c2e11aac9666dd097f2c620852c3951a4376a2f46fe2f73e1cf310a168d56baa5575a8319389d7bfa6b29ee2d908305791434",

            "039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b869073a5ffcc6fc7a28c30723d6e58ce577356982d65b833a5a5c15bf9024b43d980000000000000000000000000000000000000000000000000000000000000009",
            "19f75b9dd68c080a688774a6213f131e3052bd353a304a189d7a2ee367e3c2582612f545fb9fc89fde80fd81c68fc7dcb27fea5fc124eeda69433cf5c46d2d7f",

            "039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b869073a5ffcc6fc7a28c30723d6e58ce577356982d65b833a5a5c15bf9024b43d980000000000000000000000000000000000000000000000000000000000000001",
            "039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b869073a5ffcc6fc7a28c30723d6e58ce577356982d65b833a5a5c15bf9024b43d98",
        ]

        i = 0
        while i < len(cases):
            in_val = cases[i]
            out_val = cases[i+1]
            abi = "652dcd30"
            abi += in_val
            ret = self.send_and_call_method(abi, point=True)
            if should_fail:
                assert_equal(ret, in_val[0:128])
            else:
                assert_equal(ret, out_val)
            i += 2

    def bn256pairing_test(self, should_fail=False):
        cases = [
            "1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f593034dd2920f673e204fee2811c678745fc819b55d3e9d294e45c9b03a76aef41209dd15ebff5d46c4bd888e51a93cf99a7329636c63514396b4a452003a35bf704bf11ca01483bfa8b34b43561848d28905960114c8ac04049af4b6315a416782bb8324af6cfc93537a2ad1a445cfd0ca2a71acd7ac41fadbf933c2a51be344d120a2a4cf30c1bf9845f20c6fe39e07ea2cce61f0c9bb048165fe5e4de877550111e129f1cf1097710d41c4ac70fcdfa5ba2023c6ff1cbeac322de49d1b6df7c2032c61a830e3c17286de9462bf242fca2883585b93870a73853face6a6bf411198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa",
            "0000000000000000000000000000000000000000000000000000000000000001",
            
            "2eca0c7238bf16e83e7a1e6c5d49540685ff51380f309842a98561558019fc0203d3260361bb8451de5ff5ecd17f010ff22f5c31cdf184e9020b06fa5997db841213d2149b006137fcfb23036606f848d638d576a120ca981b5b1a5f9300b3ee2276cf730cf493cd95d64677bbb75fc42db72513a4c1e387b476d056f80aa75f21ee6226d31426322afcda621464d0611d226783262e21bb3bc86b537e986237096df1f82dff337dd5972e32a8ad43e28a78a96a823ef1cd4debe12b6552ea5f06967a1237ebfeca9aaae0d6d0bab8e28c198c5a339ef8a2407e31cdac516db922160fa257a5fd5b280642ff47b65eca77e626cb685c84fa6d3b6882a283ddd1198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa",
            "0000000000000000000000000000000000000000000000000000000000000001",
            
            "0f25929bcb43d5a57391564615c9e70a992b10eafa4db109709649cf48c50dd216da2f5cb6be7a0aa72c440c53c9bbdfec6c36c7d515536431b3a865468acbba2e89718ad33c8bed92e210e81d1853435399a271913a6520736a4729cf0d51eb01a9e2ffa2e92599b68e44de5bcf354fa2642bd4f26b259daa6f7ce3ed57aeb314a9a87b789a58af499b314e13c3d65bede56c07ea2d418d6874857b70763713178fb49a2d6cd347dc58973ff49613a20757d0fcc22079f9abd10c3baee245901b9e027bd5cfc2cb5db82d4dc9677ac795ec500ecd47deee3b5da006d6d049b811d7511c78158de484232fc68daf8a45cf217d1c2fae693ff5871e8752d73b21198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa",
            "0000000000000000000000000000000000000000000000000000000000000001",
            
            "2f2ea0b3da1e8ef11914acf8b2e1b32d99df51f5f4f206fc6b947eae860eddb6068134ddb33dc888ef446b648d72338684d678d2eb2371c61a50734d78da4b7225f83c8b6ab9de74e7da488ef02645c5a16a6652c3c71a15dc37fe3a5dcb7cb122acdedd6308e3bb230d226d16a105295f523a8a02bfc5e8bd2da135ac4c245d065bbad92e7c4e31bf3757f1fe7362a63fbfee50e7dc68da116e67d600d9bf6806d302580dc0661002994e7cd3a7f224e7ddc27802777486bf80f40e4ca3cfdb186bac5188a98c45e6016873d107f5cd131f3a3e339d0375e58bd6219347b008122ae2b09e539e152ec5364e7e2204b03d11d3caa038bfc7cd499f8176aacbee1f39e4e4afc4bc74790a4a028aff2c3d2538731fb755edefd8cb48d6ea589b5e283f150794b6736f670d6a1033f9b46c6f5204f50813eb85c8dc4b59db1c5d39140d97ee4d2b36d99bc49974d18ecca3e7ad51011956051b464d9e27d46cc25e0764bb98575bd466d32db7b15f582b2d5c452b36aa394b789366e5e3ca5aabd415794ab061441e51d01e94640b7e3084a07e02c78cf3103c542bc5b298669f211b88da1679b0b64a63b7e0e7bfe52aae524f73a55be7fe70c7e9bfc94b4cf0da1213d2149b006137fcfb23036606f848d638d576a120ca981b5b1a5f9300b3ee2276cf730cf493cd95d64677bbb75fc42db72513a4c1e387b476d056f80aa75f21ee6226d31426322afcda621464d0611d226783262e21bb3bc86b537e986237096df1f82dff337dd5972e32a8ad43e28a78a96a823ef1cd4debe12b6552ea5f",
            "0000000000000000000000000000000000000000000000000000000000000001",
            
            "20a754d2071d4d53903e3b31a7e98ad6882d58aec240ef981fdf0a9d22c5926a29c853fcea789887315916bbeb89ca37edb355b4f980c9a12a94f30deeed30211213d2149b006137fcfb23036606f848d638d576a120ca981b5b1a5f9300b3ee2276cf730cf493cd95d64677bbb75fc42db72513a4c1e387b476d056f80aa75f21ee6226d31426322afcda621464d0611d226783262e21bb3bc86b537e986237096df1f82dff337dd5972e32a8ad43e28a78a96a823ef1cd4debe12b6552ea5f1abb4a25eb9379ae96c84fff9f0540abcfc0a0d11aeda02d4f37e4baf74cb0c11073b3ff2cdbb38755f8691ea59e9606696b3ff278acfc098fa8226470d03869217cee0a9ad79a4493b5253e2e4e3a39fc2df38419f230d341f60cb064a0ac290a3d76f140db8418ba512272381446eb73958670f00cf46f1d9e64cba057b53c26f64a8ec70387a13e41430ed3ee4a7db2059cc5fc13c067194bcc0cb49a98552fd72bd9edb657346127da132e5b82ab908f5816c826acb499e22f2412d1a2d70f25929bcb43d5a57391564615c9e70a992b10eafa4db109709649cf48c50dd2198a1f162a73261f112401aa2db79c7dab1533c9935c77290a6ce3b191f2318d198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa",
            "0000000000000000000000000000000000000000000000000000000000000001",
        
            "1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f593034dd2920f673e204fee2811c678745fc819b55d3e9d294e45c9b03a76aef41209dd15ebff5d46c4bd888e51a93cf99a7329636c63514396b4a452003a35bf704bf11ca01483bfa8b34b43561848d28905960114c8ac04049af4b6315a416782bb8324af6cfc93537a2ad1a445cfd0ca2a71acd7ac41fadbf933c2a51be344d120a2a4cf30c1bf9845f20c6fe39e07ea2cce61f0c9bb048165fe5e4de877550111e129f1cf1097710d41c4ac70fcdfa5ba2023c6ff1cbeac322de49d1b6df7c103188585e2364128fe25c70558f1560f4f9350baf3959e603cc91486e110936198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa",
            "0000000000000000000000000000000000000000000000000000000000000000",
        
            "",
            "0000000000000000000000000000000000000000000000000000000000000001",
            
            "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa",
            "0000000000000000000000000000000000000000000000000000000000000000",
 
            "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d",
            "0000000000000000000000000000000000000000000000000000000000000001",

            "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa",
            "0000000000000000000000000000000000000000000000000000000000000001",

            "105456a333e6d636854f987ea7bb713dfd0ae8371a72aea313ae0c32c0bf10160cf031d41b41557f3e7e3ba0c51bebe5da8e6ecd855ec50fc87efcdeac168bcc0476be093a6d2b4bbf907172049874af11e1b6267606e00804d3ff0037ec57fd3010c68cb50161b7d1d96bb71edfec9880171954e56871abf3d93cc94d745fa114c059d74e5b6c4ec14ae5864ebe23a71781d86c29fb8fb6cce94f70d3de7a2101b33461f39d9e887dbb100f170a2345dde3c07e256d1dfa2b657ba5cd030427000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000021a2c3013d2ea92e13c800cde68ef56a294b883f6ac35d25f587c09b1b3c635f7290158a80cd3d66530f74dc94c94adb88f5cdb481acca997b6e60071f08a115f2f997f3dbd66a7afe07fe7862ce239edba9e05c5afff7f8a1259c9733b2dfbb929d1691530ca701b4a106054688728c9972c8512e9789e9567aae23e302ccd75",
            "0000000000000000000000000000000000000000000000000000000000000001",

            "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed275dc4a288d1afb3cbb1ac09187524c7db36395df7be3b99e673b13a075a65ec1d9befcd05a5323e6da4d435f3b617cdb3af83285c2df711ef39c01571827f9d",
            "0000000000000000000000000000000000000000000000000000000000000001",
 
            "00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002203e205db4f19b37b60121b83a7333706db86431c6d835849957ed8c3928ad7927dc7234fd11d3e8c36c59277c3e6f149d5cd3cfa9a62aee49f8130962b4b3b9195e8aa5b7827463722b8c153931579d3505566b4edf48d498e185f0509de15204bb53b8977e5f92a0bc372742c4830944a59b4fe6b1c0466e2a6dad122b5d2e030644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd31a76dae6d3272396d0cbe61fced2bc532edac647851e3ac53ce1cc9c7e645a83198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c21800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa",
            "0000000000000000000000000000000000000000000000000000000000000001",
            
            "105456a333e6d636854f987ea7bb713dfd0ae8371a72aea313ae0c32c0bf10160cf031d41b41557f3e7e3ba0c51bebe5da8e6ecd855ec50fc87efcdeac168bcc0476be093a6d2b4bbf907172049874af11e1b6267606e00804d3ff0037ec57fd3010c68cb50161b7d1d96bb71edfec9880171954e56871abf3d93cc94d745fa114c059d74e5b6c4ec14ae5864ebe23a71781d86c29fb8fb6cce94f70d3de7a2101b33461f39d9e887dbb100f170a2345dde3c07e256d1dfa2b657ba5cd030427000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000021a2c3013d2ea92e13c800cde68ef56a294b883f6ac35d25f587c09b1b3c635f7290158a80cd3d66530f74dc94c94adb88f5cdb481acca997b6e60071f08a115f2f997f3dbd66a7afe07fe7862ce239edba9e05c5afff7f8a1259c9733b2dfbb929d1691530ca701b4a106054688728c9972c8512e9789e9567aae23e302ccd75",
            "0000000000000000000000000000000000000000000000000000000000000001"
        ]
        
        i = 0
        while i < len(cases):
            print(i)
            in_val = cases[i]
            out_val = cases[i+1]
            abi = "1a0ffebe"
            abi += "20".zfill(64)
            abi += hex(len(in_val) // 2)[2:].zfill(64)
            abi += in_val
            ret = self.send_and_call_method(abi)
            if should_fail:
                assert_equal(ret, "0"*64)
            else:
                assert_equal(ret, out_val)
            i += 2

    def run_test(self):
        self.nodes[0].generate(COINBASE_MATURITY+50)
        self.node = self.nodes[0]
        """
        pragma solidity ^0.5;

        contract PrecompilesTest {
            uint256 public ret;
            uint256 public pointX;
            uint256 public pointY;

            function reset() public {
                ret = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;
                pointX = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;
                pointY = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;
            }

            function ecrecover_test(bytes32 h, uint8 v, bytes32 r, bytes32 s) public {
                ret = uint256(ecrecover(h, v, r, s));
            }

            function sha256_test(bytes memory data) public {
                ret = uint256(sha256(data));
            }

            function ripemd160_test(bytes memory data) public {
                ret = uint256(bytes32(ripemd160(data)));
            }

            function identity_test(bytes memory data) public {
                uint256 o;
                uint256 size = data.length;
                assembly {
                    let p := mload(0x40)
                    let success := call(sub(gas, 2000), 0x04, 0, add(data, 0x20), size, p, size)
                    switch success case 0 {
                        o := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
                    } default {
                        o := mload(p)
                    }
                }
                ret = o;
            }

            function expmod_test(uint256 base, uint256 e, uint256 m) public {
                uint256 o;
                assembly {
                    let p := mload(0x40)
                    mstore(p, 0x20)
                    mstore(add(p, 0x20), 0x20)
                    mstore(add(p, 0x40), 0x20)
                    mstore(add(p, 0x60), base)
                    mstore(add(p, 0x80), e)
                    mstore(add(p, 0xa0), m)
                    let success := call(sub(gas, 2000), 0x05, 0, p, 0xc0, p, 0x20)
                    switch success case 0 {
                        o := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
                    } default {
                        o := mload(p)
                    }
                }
                ret = o;
            }

            function bn256add_test(uint256[2] memory pointA, uint256[2] memory pointB) public {
                uint256 localX;
                uint256 localY;
                uint256 size = 0x80;
                assembly {
                    let p := mload(0x40)
                    mstore(add(p, 0x0), mload(pointA))
                    mstore(add(p, 0x20), mload(add(pointA, 0x20)))
                    mstore(add(p, 0x40), mload(pointB))
                    mstore(add(p, 0x60), mload(add(pointB, 0x20)))
                    let success := call(sub(gas, 2000), 0x06, 0, p, size, p, 0x40)
                    switch success case 0 {
                        localX := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
                        localY := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
                    } default {
                        localX := mload(p)
                        localY := mload(add(p, 0x20))
                    }
                }
                pointX = localX;
                pointY = localY;
            }

            function bn256scalarmul_test(uint256[2] memory point, uint256 scalar) public {
                uint256 localX;
                uint256 localY;
                uint256 size = 0x60;
                assembly {
                    let p := mload(0x40)
                    mstore(add(p, 0x0), mload(point))
                    mstore(add(p, 0x20), mload(add(point, 0x20)))
                    mstore(add(p, 0x40), scalar)
                    let success := call(sub(gas, 2000), 0x07, 0, p, size, p, 0x40)
                    switch success case 0 {
                        localX := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
                        localY := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
                    } default {
                        localX := mload(p)
                        localY := mload(add(p, 0x20))
                    }
                }
                pointX = localX;
                pointY = localY;
            }

            function bn256pairing_test(bytes memory points) public {
                uint256 o;
                uint256 size = points.length;
                assembly {
                    let p := mload(0x40)
                    let success := call(sub(gas, 2000), 0x08, 0, add(points, 0x20), size, p, 0x20)
                    switch success case 0 {
                        o := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
                    } default {
                        o := mload(p)
                    }
                }
                ret = o;
            }
        }

        5327e297: bn256add_test(uint256[2],uint256[2])
        1a0ffebe: bn256pairing_test(bytes)
        652dcd30: bn256scalarmul_test(uint256[2],uint256)
        7c1886d9: ecrecover_test(bytes32,uint8,bytes32,bytes32)
        fdcd12cb: expmod_test(uint256,uint256,uint256)
        3d9c8fdb: identity_test(bytes)
        767f2a89: pointX()
        a1461eef: pointY()
        d826f88f: reset()
        1b08d96f: ret()
        e3c87216: ripemd160_test(bytes)
        12bdedd7: sha256_test(bytes)
        """
        bytecode = "608060405234801561001057600080fd5b50610b1b806100206000396000f3fe608060405234801561001057600080fd5b50600436106100d1576000357c010000000000000000000000000000000000000000000000000000000090048063767f2a891161008e578063767f2a891461043a5780637c1886d914610458578063a1461eef146104a7578063d826f88f146104c5578063e3c87216146104cf578063fdcd12cb1461058a576100d1565b806312bdedd7146100d65780631a0ffebe146101915780631b08d96f1461024c5780633d9c8fdb1461026a5780635327e29714610325578063652dcd30146103cb575b600080fd5b61018f600480360360208110156100ec57600080fd5b810190808035906020019064010000000081111561010957600080fd5b82018360208201111561011b57600080fd5b8035906020019184600183028401116401000000008311171561013d57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192905050506105cc565b005b61024a600480360360208110156101a757600080fd5b81019080803590602001906401000000008111156101c457600080fd5b8201836020820111156101d657600080fd5b803590602001918460018302840111640100000000831117156101f857600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050610681565b005b6102546106e2565b6040518082815260200191505060405180910390f35b6103236004803603602081101561028057600080fd5b810190808035906020019064010000000081111561029d57600080fd5b8201836020820111156102af57600080fd5b803590602001918460018302840111640100000000831117156102d157600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192905050506106e8565b005b6103c96004803603608081101561033b57600080fd5b8101908080604001906002806020026040519081016040528092919082600260200280828437600081840152601f19601f820116905080830192505050505050919291929080604001906002806020026040519081016040528092919082600260200280828437600081840152601f19601f8201169050808301925050505050509192919290505050610748565b005b610438600480360360608110156103e157600080fd5b8101908080604001906002806020026040519081016040528092919082600260200280828437600081840152601f19601f8201169050808301925050505050509192919290803590602001909291905050506107fd565b005b6104426108a7565b6040518082815260200191505060405180910390f35b6104a56004803603608081101561046e57600080fd5b8101908080359060200190929190803560ff16906020019092919080359060200190929190803590602001909291905050506108ad565b005b6104af610940565b6040518082815260200191505060405180910390f35b6104cd610946565b005b610588600480360360208110156104e557600080fd5b810190808035906020019064010000000081111561050257600080fd5b82018360208201111561051457600080fd5b8035906020019184600183028401116401000000008311171561053657600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192905050506109bd565b005b6105ca600480360360608110156105a057600080fd5b81019080803590602001909291908035906020019092919080359060200190929190505050610a71565b005b6002816000604051602001526040518082805190602001908083835b6020831061060b57805182526020820191506020810190506020830392506105e8565b6001836020036101000a0380198251168184511680821785525050505050509050019150506020604051808303816000866161da5a03f115801561064e57600080fd5b50505060405160208081101561066357600080fd5b81019080805190602001909291905050506001900460008190555050565b600080825190506040516020818360208701600060086107d05a03f180600081146106af57825194506106d3565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff94505b50505081600081905550505050565b60005481565b6000808251905060405181818360208701600060046107d05a03f180600081146107155782519450610739565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff94505b50505081600081905550505050565b600080600060809050604051855160008201526020860151602082015284516040820152602085015160608201526040818383600060066107d05a03f1806000811461079e5782519550602083015194506107e5565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff95507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff94505b50505082600181905550816002819055505050505050565b60008060006060905060405185516000820152602086015160208201528460408201526040818383600060076107d05a03f1806000811461084857825195506020830151945061088f565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff95507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff94505b50505082600181905550816002819055505050505050565b60015481565b60018484848460405160008152602001604052600060405160200152604051808581526020018460ff1660ff16815260200183815260200182815260200194505050505060206040516020810390808403906000866161da5a03f115801561091457600080fd5b5050506020604051035173ffffffffffffffffffffffffffffffffffffffff1660008190555050505050565b60025481565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000819055507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6001819055507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600281905550565b6003816000604051602001526040518082805190602001908083835b602083106109fc57805182526020820191506020810190506020830392506109d9565b6001836020036101000a0380198251168184511680821785525050505050509050019150506020604051808303816000866161da5a03f1158015610a3f57600080fd5b505050604051516c01000000000000000000000000026bffffffffffffffffffffffff19166001900460008190555050565b600060405160208152602080820152602060408201528460608201528360808201528260a082015260208160c083600060056107d05a03f18060008114610abb5782519350610adf565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff93505b505050806000819055505050505056fea165627a7a72305820ad8768556058f9bede07b7a64f41702df9de711a94e0312cf4d9b715fd6e05100029"
        self.contract_address = self.node.createcontract(bytecode)['address']
        self.node.generate(1)
        
        # Test without qip7 (constantinople precompiles).
        self.reset()
        self.ecrecover_test()

        self.reset()
        self.sha256_test()

        self.reset()
        self.ripemd160_test()

        self.reset()
        self.identity_test()

        self.reset()
        self.modexp_test(should_fail=True)
        
        self.reset()
        self.bn256add_test(should_fail=True)

        self.reset()
        self.bn256scalarmul_test(should_fail=True)

        self.reset()
        self.bn256pairing_test(should_fail=True)


        # Now test with qip7 (constantinople precompiles) activated.
        # All the old precompiles should still work, as well as the new contracts
        self.restart_node(0, ['-constantinopleheight=1106'])
        bytecode = "608060405234801561001057600080fd5b50610ad2806100206000396000f3fe608060405234801561001057600080fd5b50600436106100b45760003560e01c8063767f2a8911610071578063767f2a891461041d5780637c1886d91461043b578063a1461eef1461048a578063d826f88f146104a8578063e3c87216146104b2578063fdcd12cb1461056d576100b4565b806312bdedd7146100b95780631a0ffebe146101745780631b08d96f1461022f5780633d9c8fdb1461024d5780635327e29714610308578063652dcd30146103ae575b600080fd5b610172600480360360208110156100cf57600080fd5b81019080803590602001906401000000008111156100ec57600080fd5b8201836020820111156100fe57600080fd5b8035906020019184600183028401116401000000008311171561012057600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192905050506105af565b005b61022d6004803603602081101561018a57600080fd5b81019080803590602001906401000000008111156101a757600080fd5b8201836020820111156101b957600080fd5b803590602001918460018302840111640100000000831117156101db57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050610659565b005b6102376106ba565b6040518082815260200191505060405180910390f35b6103066004803603602081101561026357600080fd5b810190808035906020019064010000000081111561028057600080fd5b82018360208201111561029257600080fd5b803590602001918460018302840111640100000000831117156102b457600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192905050506106c0565b005b6103ac6004803603608081101561031e57600080fd5b8101908080604001906002806020026040519081016040528092919082600260200280828437600081840152601f19601f820116905080830192505050505050919291929080604001906002806020026040519081016040528092919082600260200280828437600081840152601f19601f8201169050808301925050505050509192919290505050610720565b005b61041b600480360360608110156103c457600080fd5b8101908080604001906002806020026040519081016040528092919082600260200280828437600081840152601f19601f8201169050808301925050505050509192919290803590602001909291905050506107d5565b005b61042561087f565b6040518082815260200191505060405180910390f35b6104886004803603608081101561045157600080fd5b8101908080359060200190929190803560ff1690602001909291908035906020019092919080359060200190929190505050610885565b005b61049261090e565b6040518082815260200191505060405180910390f35b6104b0610914565b005b61056b600480360360208110156104c857600080fd5b81019080803590602001906401000000008111156104e557600080fd5b8201836020820111156104f757600080fd5b8035906020019184600183028401116401000000008311171561051957600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050919291929050505061098b565b005b6105ad6004803603606081101561058357600080fd5b81019080803590602001909291908035906020019092919080359060200190929190505050610a28565b005b6002816040518082805190602001908083835b602083106105e557805182526020820191506020810190506020830392506105c2565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa158015610627573d6000803e3d6000fd5b5050506040513d602081101561063c57600080fd5b810190808051906020019092919050505060001c60008190555050565b600080825190506040516020818360208701600060086107d05a03f1806000811461068757825194506106ab565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff94505b50505081600081905550505050565b60005481565b6000808251905060405181818360208701600060046107d05a03f180600081146106ed5782519450610711565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff94505b50505081600081905550505050565b600080600060809050604051855160008201526020860151602082015284516040820152602085015160608201526040818383600060066107d05a03f180600081146107765782519550602083015194506107bd565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff95507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff94505b50505082600181905550816002819055505050505050565b60008060006060905060405185516000820152602086015160208201528460408201526040818383600060076107d05a03f18060008114610820578251955060208301519450610867565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff95507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff94505b50505082600181905550816002819055505050505050565b60015481565b60018484848460405160008152602001604052604051808581526020018460ff1660ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa1580156108e2573d6000803e3d6000fd5b5050506020604051035173ffffffffffffffffffffffffffffffffffffffff1660008190555050505050565b60025481565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6000819055507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6001819055507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600281905550565b6003816040518082805190602001908083835b602083106109c1578051825260208201915060208101905060208303925061099e565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa158015610a03573d6000803e3d6000fd5b5050506040515160601b6bffffffffffffffffffffffff191660001c60008190555050565b600060405160208152602080820152602060408201528460608201528360808201528260a082015260208160c083600060056107d05a03f18060008114610a725782519350610a96565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff93505b505050806000819055505050505056fea165627a7a7230582067f822d1339f29c535c6013b09d2374c1f589e39e98a74012a3519186ee9b2630029"
        self.contract_address = self.node.createcontract(bytecode)['address']
        self.node.generate(1)

        self.reset()
        self.ecrecover_test()

        self.reset()
        self.sha256_test()

        self.reset()
        self.ripemd160_test()

        self.reset()
        self.identity_test()

        self.reset()
        self.modexp_test(should_fail=False)
        
        self.reset()
        self.bn256add_test(should_fail=False)

        self.reset()
        self.bn256scalarmul_test(should_fail=False)

        self.reset()
        self.bn256pairing_test(should_fail=False)

if __name__ == '__main__':
    QtumEVMConstantinoplePrecompiledContractsTest().main()
